#include "device.h"
#include <string.h>
#include "device_def.h"
#include "device_port.h"

Dev_Ret_t
device_open(DevDesc_t* pstDevDesc)
{
    // 防止设备重复打开
    if(NULL != *(pstDevDesc->pstDevice))
    {
        return DEV_IS_OPEN;
    }
    
    // 设备描述为空
    if(NULL == pstDevDesc)
    {
        return DEV_DESC_NULL;
    }

    // 设备上下文为空
    if(NULL == pstDevDesc->pvContext || 0 == pstDevDesc->u16Size)
    {
        return DEV_CONTEXT_NULL;
    }

    // 设备类型合法性检测
    if(DEV_TYPE_SIZE <= pstDevDesc->u8Type)
    {
        return DEV_TYPE_ERR;
    }

    // 申请内存
    void* pvMem = DEV_MALLOC(DEV_SIZE + pstDevDesc->u16Size);
    if(NULL == pvMem)
    {
        return DEV_MALLOC_ERR;
    }

    // 设备结构体
    *(pstDevDesc->pstDevice) = (Device_t*)pvMem;

    // 设备上下文
    void* pvContext = (void*)((uint8_t*)pvMem + DEV_SIZE);

    // 复制设备上下文
    memcpy(pvContext, pstDevDesc->pvContext, pstDevDesc->u16Size);

    // 初始化设备结构体
    (*(pstDevDesc->pstDevice))->u8Type               = pstDevDesc->u8Type;
    (*(pstDevDesc->pstDevice))->pvContext            = pvContext;
    (*(pstDevDesc->pstDevice))->stEvent.u16Event     = 0;

    // 返回成功
    return DEV_OK;
}

Dev_Ret_t
device_close(Device_t *pstDevice)
{

    (void) pstDevice;
    
    // 注销设备
    pstDevice = NULL;

    // 注销设备上下文
    pstDevice->pvContext = NULL;

    // 释放设备结构体

    // 释放设备上下文结构体

    return DEV_OK;
}

Dev_Ret_t
device_read(Device_t *pstDevice, uint8_t* pu8Buf, uint32_t u32Len)
{
    // 设备结构体为空
    if(NULL == pstDevice)
    {
        return DEV_NULL;
    }

    // 数据为空
    if(NULL == pu8Buf)
    {
        return DEV_DATA_NULL;
    }

    // 数据长度错误
    if(DEV_EVT_DESC_SIZE != u32Len)
    {
        return DEV_DATA_SIZE_ERR;
    }

    // 设备状态检测
    DEV_CHECK_STATUS(pstDevice);

    // 设置设备繁忙
    DEV_SET_BUSY(pstDevice);

    // 获取事件描述
    DevEvtDesc_t* pstEvtDesc = (DevEvtDesc_t*)pu8Buf;

    // 获取参数
    uint8_t u8Bit = pstEvtDesc->u8EvtBit;

    // 事件位溢出
    if(MAX_EVENT_BITS <= u8Bit) 
    {
        return DEV_EVT_OVERFLOW;
    }

    // 获取事件位
    uint16_t u16Value = pstDevice->stEvent.u16Event;
    pstEvtDesc->u8EvtState = (u16Value >> u8Bit) & 0x01;

    // 设备空闲
    DEV_SET_IDLE(pstDevice);

    // 返回成功
    return DEV_OK;
}

Dev_Ret_t
device_write(Device_t *pstDevice, uint8_t* pu8Buf, uint32_t u32Len)
{
    // 设备结构体为空
    if(NULL == pstDevice)
    {
        return DEV_NULL;
    }

    // 数据为空
    if(NULL == pu8Buf)
    {
        return DEV_DATA_NULL;
    }

    // 数据长度错误
    if(DEV_EVT_DESC_SIZE != u32Len)
    {
        return DEV_DATA_SIZE_ERR;
    }

    // 设备状态检测
    DEV_CHECK_STATUS(pstDevice);

    // 设置设备繁忙
    DEV_SET_BUSY(pstDevice);
    
    // 获取事件描述
    DevEvtDesc_t* pstEvtDesc = (DevEvtDesc_t*)pu8Buf;

    // 获取参数
    uint8_t u8Bit   = pstEvtDesc->u8EvtBit;
    uint8_t u8Value = pstEvtDesc->u8EvtState;

    // 事件位溢出
    if(MAX_EVENT_BITS <= u8Bit) 
    {
        return DEV_EVT_OVERFLOW;
    }

    // 获取事件
    uint16_t u16Value = pstDevice->stEvent.u16Event;

    // 处理事件
    (EVENT_STATUS_SET == u8Value) ? (u16Value |= (1U << u8Bit)) : (u16Value &= ~(1U << u8Bit));

    // 更新事件
    pstDevice->stEvent.u16Event = u16Value;

    // 设备空闲
    DEV_SET_IDLE(pstDevice);

    // 返回成功
    return DEV_OK;
}

Dev_Ret_t
device_ioctl(Device_t *pstDevice, uint8_t u8Cmd, void *pvArg)
{
    // 设备结构体为空
    if(NULL == pstDevice)
    {
        return DEV_NULL;
    }

    // 设备上下文为空
    if(NULL == pstDevice->pvContext)
    {
        return DEV_CONTEXT_NULL;
    }

    // 设备类型合法性检测
    uint8_t u8Type = pstDevice->u8Type;
    if(DEV_TYPE_SIZE <= u8Type)
    {
        return DEV_TYPE_ERR;
    }

    // 设备状态检测
    DEV_CHECK_STATUS(pstDevice);

    // 设置设备繁忙
    DEV_SET_BUSY(pstDevice);

    // 调用设备的ioctl处理函数
    Dev_Ret_t eRet = DEV_OK;
    pfn_ioctl_t pfnIoctl = g_stDevIoctlMap[u8Type];
    eRet = (NULL != pfnIoctl) ? pfnIoctl(pstDevice, u8Cmd, pvArg) : DEV_IOCTL_NULL;
    
    // 设备空闲
    DEV_SET_IDLE(pstDevice);

    // 返回成功
    return eRet;
}
